#include <iostream>
#include <string.h>
using std::cout;
using std::endl;
using std ::ostream;

class CowString
{
    class CharProxy{
        public:
            CharProxy(CowString & self,int idx)
            :_self(self)
        private:
            CowString & _self;
            int _idx;
    };

public:
    CowString();
    CowString(const char* pstr);
    CowString(const CowString & rhs);
    CowString & operator=(const CowString & rhs);
    ~CowString();
    
    int size()const{
        return strlen(_pstr);
    }

    const char * c_str() const{
        return _pstr;
    }

    int use_count(){
        return *(int*)(_pstr - kRefcountLength);
    }

private:
    char* malloc(const char* pstr = nullptr){
        if(_pstr){
            return new char[strlen(pstr) + kRefcountLength]() + kRefcountLength;
        }else{
            return new char[1 + kRefcountLength]() + kRefcountLength;
        }
    }

    void initRefcount(){
        *(int*)(_pstr - kRefcountLength) = 1;//char* -> int* 解引用
    }

    void increaseRefcount(){
        ++*(int*)(_pstr - kRefcountLength);
    }

    void decreaseRefcount(){
        --*(int*)(_pstr - kRefcountLength);
    }

    void release(){
        decreaseRefcount();
        if(use_count() == 0){
            delete [] (_pstr - kRefcountLength);
            cout << ">> delete heap" << endl;
        }
        _pstr = nullptr;
    }

private:
    char* _pstr;
    static const int kRefcountLength = 4;
};

CowString::CowString()
:_pstr(malloc())
{
    cout << "CowString()" << endl;
    initRefcount();
}

CowString::CowString(const char* pstr)
:_pstr(malloc())
{
    cout << "CowString(const char*)" << endl;
    strcpy(_pstr,pstr);
    initRefcount();
}

CowString::CowString(const CowString & rhs)
:_pstr(rhs._pstr)
{
    increaseRefcount();
    cout << "CowString(const CowString & rhs)" << endl;
}

CowString & CowString::operator=(const CowString & rhs){
    //自复制
    if(this != &rhs){
        release();
        _pstr = rhs._pstr;
        increaseRefcount();
    }
    return *this;
}

CowString::~CowString(){
    cout << "~CowString()" << endl;
    release();
}

void test0(){

}

int main(int argc, char * argv[])
{
    test0();
    return 0;
}


